package com.gsbelarus.gedemin.income;

import android.content.Context;

import com.gsbelarus.gedemin.income.table.ClientsTable;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.List;

public class SumFormatter {

    private Context context;

    private static final long TEN_BILLION = 10000000000L;
    private static final int TEN_MILLION = 10000000;
    private static final int MILLION = 1000000;
    private static final int THOUSAND = 1000;

    /**
     * формат, в чем отображаем суммы.
     * FORMAT_IN_MILLION - делим сумму на миллион.
     * FORMAT_IN_THOUSAND - делим сумму на тысячу.
     * FORMAT_IN_RUB - делим сумму на 1.
     */
    public enum Format {
        FORMAT_IN_MILLION(MILLION),
        FORMAT_IN_THOUSAND(THOUSAND),
        FORMAT_IN_RUB(1),
        FORMAT_NO_DATA(2),
        FORMAT_NULL(3);

        private long i;

        Format(long i) {
            this.i = i;
        }

        public long getFormat() {
            return i;
        }
    }

    public Format format = Format.FORMAT_NULL;

    private DecimalFormat formatter;

    public SumFormatter(Context context) {
        this.context = context;
        initDecimalFormat();
    }

    public SumFormatter(Context context, Format format) {
        this.context = context;
        this.format = format;
        initDecimalFormat();
    }

    private void initDecimalFormat() {
        formatter = new DecimalFormat("#,###,###");
        DecimalFormatSymbols custom = new DecimalFormatSymbols();
        custom.setGroupingSeparator(' ');
        custom.setDecimalSeparator('.');
        formatter.setDecimalFormatSymbols(custom);
    }

    public void checkFormat(List<ClientsTable> sums) {
        long maxSum = 0;
        long minSum = Long.MAX_VALUE;

        for (ClientsTable sum : sums) {
            long planSum = sum.getPlanSum();
            long paidSum = sum.getPaidSum();

            /** находим макс сумму*/
            maxSum = checkMax(paidSum, maxSum);
            maxSum = checkMax(planSum, maxSum);

            /** находим мин сумму*/
            minSum = checkMinWithoutZero(paidSum, minSum);
            minSum = checkMinWithoutZero(planSum, minSum);
        }
        /** анализируем в какой формете отображать суммы */
        check(minSum, maxSum);
    }

    /**
     * Применение формата для суммы
     *
     * @param sum сумма
     * @return сумма в определенном формате
     */
    public String format(long sum) {
        if (format == Format.FORMAT_NULL) {
            check(sum, sum);
        }
        return formatter.format(sum / format.getFormat());
    }

    /**
     * Преобразование long sum в String вида "#,###,###" без окгругления
     *
     * @param sum сумма
     * @return сумма преобразованная в строку
     */
    public String formatWithoutRounding(long sum) {
        format = Format.FORMAT_IN_RUB;
        return formatter.format(sum);
    }

    /**
     * @return формат суммы (млн. руб. / тыс. руб. / руб.
     */
    public String formatText() {
        switch (format) {
            case FORMAT_IN_MILLION:
                return context.getString(R.string.format_sum_million) + " " + context.getString(R.string.format_sum_rub);
            case FORMAT_IN_THOUSAND:
                return context.getString(R.string.format_sum_thousand) + " " + context.getString(R.string.format_sum_rub);
            case FORMAT_IN_RUB:
                return context.getString(R.string.format_sum_rub);
            case FORMAT_NO_DATA:
                return "";
            default:
                return null;
        }
    }

    private void check(long min, long max) {
        /** если есть сумма больше 10 миллиардов и нет суммы меньше миллиона, отображаем в миллионах */
        if (isMore(max, TEN_BILLION) && isMore(min, MILLION - 1))
            format = Format.FORMAT_IN_MILLION;

        /** если есть сумма больше 10 миллионов и нет суммы меньше тысячи, отображаем в миллионах */
        else if (isMore(max, TEN_MILLION) && isMore(min, THOUSAND - 1))
            format = Format.FORMAT_IN_THOUSAND;

        /** если в данных все суммы нули, ничего не отображаем */
        else if (max == 0)
            format = Format.FORMAT_NO_DATA;

        /** во всех других случаях отображаем в рублях */
        else format = Format.FORMAT_IN_RUB;
    }

    private long checkMax(long sum, long max) {
        return (sum > max) ? sum : max;
    }

    private long checkMinWithoutZero(long sum, long min) {
        return (sum < min && sum > 0) ? sum : min;
    }

    private boolean isMore(long first, long second) {
        return (first > second) ? true : false;
    }
}
